#include "eventmanager.hpp"

using namespace Shiny;

EventManager* EventManager::_instance = 0;

EventManager::EventManager()
{
  if (!_instance)
    _instance = this;
}

EventManager* EventManager::Get(void)
{
  return (_instance);
}

bool EventManager::Run(sf::RenderWindow& app)
{
  sf::Event   event;

  while (app.PollEvent(event))
  {
    bool isMouseEvent = IS_MOUSE_EVENT(event);

    if (event.Type == sf::Event::Closed)
      return (false);
    if ((isMouseEvent && (_mouseManager.ReceiveEvent(event))) ||
        (_controlManager.ReceiveEvent(event)))
      continue ;
    if (!isMouseEvent) WidgetsEventObserver.Emit(event);
  }
  return (true);
}

/*
 * EventManager::Mouse
 */
EventManager::Mouse::Mouse()
{
  _waitingButtonRelease = 0;
  _waitingMouseMove     = 0;
}

void EventManager::Mouse::ExpectMouseRelease(EventManager::Mouse::Listener* listener)
{
  if (_waitingButtonRelease)
    _waitingButtonRelease->ExpectedMouseRelease();
  _waitingButtonRelease = listener;
}

void EventManager::Mouse::ExpectMouseMove(EventManager::Mouse::Listener* listener)
{
  if (_waitingMouseMove && _waitingMouseMove != listener)
    _waitingMouseMove->ExpectedMouseMove();
  _waitingMouseMove = listener;
}

void EventManager::Mouse::HandleExpectedEvents(const sf::Event event)
{
  if (event.Type == sf::Event::MouseButtonReleased && _waitingButtonRelease)
  {
    _waitingButtonRelease->ExpectedMouseRelease();
    _waitingButtonRelease = 0;
  }
}

bool EventManager::Mouse::ReceiveEvent(const sf::Event event)
{
  EventManager::Mouse::Listeners::iterator current;
  EventManager::Mouse::Listeners::iterator end   = _listeners.end();
  bool                                     toRet = false;

  for (current = _listeners.begin() ; current != end ; ++current)
  {
    if ((*current)->mouseEvent(event))
    {
      toRet = true;
      break ;
    }
  }
  if (toRet == false)
    ExpectMouseMove(0);
  HandleExpectedEvents(event);
  return (toRet);
}

void EventManager::Mouse::AddListener(EventManager::Mouse::Listener* listener)
{
  _listeners.remove(listener);
  _listeners.insert(_listeners.begin(), listener);
}

void EventManager::Mouse::DelListener(EventManager::Mouse::Listener* listener)
{
  _listeners.remove(listener);
  if (_waitingButtonRelease == listener) _waitingButtonRelease = 0;
  if (_waitingMouseMove     == listener) _waitingMouseMove     = 0;
}

void EventManager::Mouse::SetFocus(EventManager::Mouse::Listener* listener)
{
  AddListener(listener);
}

/*
 * EventManager::Mouse::Event
 */
EventManager::Mouse::Event::Event(sf::Event event) : event(event)
{
  switch (event.Type)
  {
    case sf::Event::MouseButtonPressed:
    case sf::Event::MouseButtonReleased:
      position.x = event.MouseButton.X;
      position.y = event.MouseButton.Y;
      break ;
    case sf::Event::MouseWheelMoved:
      position.x = event.MouseWheel.X;
      position.y = event.MouseWheel.Y;
      break ;
    case sf::Event::MouseMoved:
      position.x = event.MouseMove.X;
      position.y = event.MouseMove.Y;
      break ;
  }
}
